package com.lottery.common.service.Impl;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.aliyun.oss.HttpMethod;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.CopyObjectResult;
import com.aliyun.oss.model.GeneratePresignedUrlRequest;
import com.aliyun.oss.model.OSSObject;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.aliyuncs.sts.model.v20150401.AssumeRoleRequest;
import com.aliyuncs.sts.model.v20150401.AssumeRoleResponse;
import com.lottery.common.contants.Constants;
import com.lottery.common.contants.ReQueryResult;
import com.lottery.common.dao.SysConfigMapper;
import com.lottery.common.entity.SysConfig;
import com.lottery.common.model.AliyunOss;
import com.lottery.common.model.AliyunSTS;
import com.lottery.common.service.FileUploadService;
import com.lottery.common.utils.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.nutz.lang.util.NutMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.*;
import java.net.URL;
import java.util.Date;
import java.util.List;

@Slf4j
@Service
public class FileUploadServiceImpl implements FileUploadService {
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Resource
    private SysConfigMapper configMapper;
    private ReQueryResult result;

    @Autowired
    private AliyunOss oss;

    @Value("${base.upload.path}")
    private String uploadPath;

    @Override
    public ReQueryResult uploadFile(String fileName,InputStream file,String type) {
        result=new ReQueryResult();

        // 创建OSSClient实例。
        OSS ossClient =  new OSSClientBuilder().build(oss.getEndpoint(), oss.getAccessKeyId(), oss.getAccessKeySecret());
        // 上传文件。<yourLocalFile>由本地文件路径加文件名包括后缀组成，例如/users/local/myfile.txt。
        ossClient.putObject(oss.getBucketName(), fileName, file);
        // 关闭OSSClient。
        ossClient.shutdown();


        result.success(Constants.SUCCESS_DESC);
        return result;
    }

    @Override
    public  void testUploadFile(String fileName,InputStream file,String type){
        ReQueryResult result=getSTSToken();
        if (result.getResultCode()!=ReQueryResult.TYPE_ZERO_ZERO_STR)
            return;
        AliyunSTS aliyunSTS= (AliyunSTS) result.getData();
        OSS ossClient =  new OSSClientBuilder().build(oss.getEndpoint(), aliyunSTS.getAccessKeyId(), aliyunSTS.getAccessKeySecret(),aliyunSTS.getSecurityToken());
        fileName="sts"+fileName;
        ossClient.putObject(oss.getBucketName(), fileName, file);
        ossClient.shutdown();
    }


    @Override
    public ResponseEntity<byte[]> download(String fileName) {
        log.info(" user dowload in ");
        HttpHeaders headers = new HttpHeaders();
        //下载显示的文件名，解决中文名称乱码问题
        String downloadFielName = null;
        String path = uploadPath;


        ResponseEntity<byte[]> byteFIle=null;
        log.info(" fileName is {} ",fileName);
        try {
            downloadFielName = new String(fileName.getBytes("UTF-8"),"iso-8859-1");
            //通知浏览器以attachment（下载方式）打开图片
            headers.setContentDispositionFormData("attachment", downloadFielName);
            //application/octet-stream ： 二进制流数据（最常见的文件下载）。
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            byteFIle=new ResponseEntity<byte[]>(downloadFile(fileName,oss.getBucketName()),
                    headers, HttpStatus.CREATED);
        } catch (Exception e) {
            log.error(String.valueOf(e));
            e.printStackTrace();
            return byteFIle;
        } finally {
            return byteFIle;
        }
    }

    @Override
    public ReQueryResult getSTSToken() {
        result=new ReQueryResult();
        log.info("获取STS 临时凭证");
        String roleSessionName = "session-name";
        String policy = "{\n" +
                "    \"Version\": \"1\", \n" +
                "    \"Statement\": [\n" +
                "        {\n" +
                "            \"Action\": [\n" +
                "                \"oss:*\"\n" +
                "            ], \n" +
                "            \"Resource\": [\n" +
                "                \"acs:oss:*:*:*\" \n" +
                "            ], \n" +
                "            \"Effect\": \"Allow\"\n" +
                "        }\n" +
                "    ]\n" +
                "}";
        try {
            // 构造 default profile（参数留空，无需添加 region ID）
            IClientProfile profile = DefaultProfile.getProfile("", oss.getAccessKeyId(), oss.getAccessKeySecret());
            // 用 profile 构造 client
            DefaultAcsClient client = new DefaultAcsClient(profile);
            final AssumeRoleRequest request = new AssumeRoleRequest();
            request.setSysEndpoint(oss.getStsEndPoint());
            request.setSysMethod(MethodType.POST);
            request.setRoleArn(oss.getRoleArn());
            request.setRoleSessionName(roleSessionName);
            request.setPolicy(policy); // Optional
            final AssumeRoleResponse response = client.getAcsResponse(request);
            System.out.println("Expiration: " + response.getCredentials().getExpiration());
            System.out.println("Access Key Id: " + response.getCredentials().getAccessKeyId());
            System.out.println("Access Key Secret: " + response.getCredentials().getAccessKeySecret());
            System.out.println("Security Token: " + response.getCredentials().getSecurityToken());
            System.out.println("RequestId: " + response.getRequestId());
            AliyunSTS sts=new AliyunSTS();
            sts.setEndPoint(oss.getEndpoint());
            sts.setStsEndPoint(oss.getStsEndPoint());
            sts.setBucketName(oss.getBucketName());
            sts.setAccessKeyId(response.getCredentials().getAccessKeyId());
            sts.setAccessKeySecret(response.getCredentials().getAccessKeySecret());
            sts.setSecurityToken(response.getCredentials().getSecurityToken());
            sts.setRequestId(response.getRequestId());
            result.setData(sts);
            result.success(Constants.SUCCESS_DESC);
        } catch (ClientException e) {
            System.out.println("Failed：");
            System.out.println("Error code: " + e.getErrCode());
            System.out.println("Error message: " + e.getErrMsg());
            System.out.println("RequestId: " + e.getRequestId());
            result.error("sts调用失败");
        }

        return result;
    }

    public byte[] downloadFile(String fileName,String bucketName)  {
        // 创建OSSClient实例。
        OSS ossClient =  new OSSClientBuilder().build(oss.getEndpoint(), oss.getAccessKeyId(), oss.getAccessKeySecret());

        // ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
        OSSObject ossObject = ossClient.getObject(bucketName, fileName);

        // 读取文件内容。
        System.out.println("Object content:");
        InputStreamReader file=new InputStreamReader(ossObject.getObjectContent());
        byte[] bytes=null;
        try {
            bytes=toByteArray(ossObject.getObjectContent());
        } catch (IOException e) {
            e.printStackTrace();
            log.info(ExceptionUtils.getFullStackTrace(e));
        }finally {
            // 关闭OSSClient。
            ossClient.shutdown();
        }

        return bytes;
    }

    public static byte[] toByteArray(InputStream input) throws IOException {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        byte[] buffer = new byte[4096];
        int n = 0;
        while (-1 != (n = input.read(buffer))) {
            output.write(buffer, 0, n);
        }
        return output.toByteArray();
    }


}
